Proper connect_port
[juce-lv2.git] / juce / source / extras / the jucer / src / model / jucer_GeneratedCode.cpp
blobe32e223cf073c06a4b3ac2424ecaa4da7a65a7ea
1 /*
2 ==============================================================================
4 This file is part of the JUCE library - "Jules' Utility Class Extensions"
5 Copyright 2004-11 by Raw Material Software Ltd.
7 ------------------------------------------------------------------------------
9 JUCE can be redistributed and/or modified under the terms of the GNU General
10 Public License (Version 2), as published by the Free Software Foundation.
11 A copy of the license is included in the JUCE distribution, or can be found
12 online at www.gnu.org/licenses.
14 JUCE is distributed in the hope that it will be useful, but WITHOUT ANY
15 WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
16 A PARTICULAR PURPOSE. See the GNU General Public License for more details.
18 ------------------------------------------------------------------------------
20 To release a closed-source product which uses JUCE, commercial licenses are
21 available: visit www.rawmaterialsoftware.com/juce for more information.
23 ==============================================================================
26 #include "../jucer_Headers.h"
27 #include "jucer_GeneratedCode.h"
30 //==============================================================================
31 GeneratedCode::GeneratedCode (const JucerDocument* const document_)
32 : document (document_),
33 suffix (0)
37 GeneratedCode::~GeneratedCode()
41 int GeneratedCode::getUniqueSuffix()
43 return ++suffix;
46 //==============================================================================
47 String& GeneratedCode::getCallbackCode (const String& requiredParentClass,
48 const String& returnType,
49 const String& prototype,
50 const bool hasPrePostUserSections)
52 String parentClass (requiredParentClass);
53 if (parentClass.isNotEmpty()
54 && ! (parentClass.startsWith ("public ")
55 || parentClass.startsWith ("private ")
56 || parentClass.startsWith ("protected ")))
58 parentClass = "public " + parentClass;
61 for (int i = callbacks.size(); --i >= 0;)
63 CallbackMethod* const cm = callbacks.getUnchecked(i);
65 if (cm->requiredParentClass == parentClass
66 && cm->returnType == returnType
67 && cm->prototype == prototype)
68 return cm->content;
71 CallbackMethod* const cm = new CallbackMethod();
72 callbacks.add (cm);
74 cm->requiredParentClass = parentClass;
75 cm->returnType = returnType;
76 cm->prototype = prototype;
77 cm->hasPrePostUserSections = hasPrePostUserSections;
78 return cm->content;
81 void GeneratedCode::removeCallback (const String& returnType, const String& prototype)
83 for (int i = callbacks.size(); --i >= 0;)
85 CallbackMethod* const cm = callbacks.getUnchecked(i);
87 if (cm->returnType == returnType && cm->prototype == prototype)
88 callbacks.remove (i);
92 void GeneratedCode::addImageResourceLoader (const String& imageMemberName, const String& resourceName)
94 const String initialiser (imageMemberName + " (0)");
96 if (! initialisers.contains (initialiser, false))
98 initialisers.add (initialiser);
100 privateMemberDeclarations
101 << "Image " << imageMemberName << ";\n";
103 if (resourceName.isNotEmpty())
105 constructorCode
106 << imageMemberName << " = ImageCache::getFromMemory ("
107 << resourceName << ", " << resourceName << "Size);\n";
112 const StringArray GeneratedCode::getExtraParentClasses() const
114 StringArray s;
116 for (int i = 0; i < callbacks.size(); ++i)
118 CallbackMethod* const cm = callbacks.getUnchecked(i);
119 s.add (cm->requiredParentClass);
122 return s;
125 const String GeneratedCode::getCallbackDeclarations() const
127 String s;
129 for (int i = 0; i < callbacks.size(); ++i)
131 CallbackMethod* const cm = callbacks.getUnchecked(i);
133 s << cm->returnType << " " << cm->prototype << ";\n";
136 return s;
139 const String GeneratedCode::getCallbackDefinitions() const
141 String s;
143 for (int i = 0; i < callbacks.size(); ++i)
145 CallbackMethod* const cm = callbacks.getUnchecked(i);
147 const String userCodeBlockName ("User"
148 + makeValidCppIdentifier (cm->prototype.upToFirstOccurrenceOf ("(", false, false),
149 true, true, false).trim());
151 if (userCodeBlockName.isNotEmpty() && cm->hasPrePostUserSections)
153 s << cm->returnType << " " << className << "::" << cm->prototype
154 << "\n{\n //[" << userCodeBlockName << "_Pre]\n //[/" << userCodeBlockName
155 << "_Pre]\n\n "
156 << indentCode (cm->content.trim(), 4)
157 << "\n\n //[" << userCodeBlockName << "_Post]\n //[/" << userCodeBlockName
158 << "_Post]\n}\n\n";
160 else
162 s << cm->returnType << " " << className << "::" << cm->prototype
163 << "\n{\n "
164 << indentCode (cm->content.trim(), 4)
165 << "\n}\n\n";
169 return s;
172 //==============================================================================
173 const String GeneratedCode::getClassDeclaration() const
175 StringArray parentClassLines;
176 parentClassLines.addTokens (parentClasses, ",", String::empty);
177 parentClassLines.addArray (getExtraParentClasses());
179 parentClassLines.trim();
180 parentClassLines.removeEmptyStrings();
181 parentClassLines.removeDuplicates (false);
183 if (parentClassLines.contains ("public Button", false))
184 parentClassLines.removeString ("public Component", false);
186 String r ("class ");
187 r << className << " : ";
189 r += parentClassLines.joinIntoString (",\n" + String::repeatedString (" ", r.length()));
191 return r;
194 const String GeneratedCode::getInitialiserList() const
196 StringArray inits (initialisers);
198 if (parentClassInitialiser.isNotEmpty())
199 inits.insert (0, parentClassInitialiser);
201 inits.trim();
202 inits.removeEmptyStrings();
203 inits.removeDuplicates (false);
205 String s;
207 if (inits.size() == 0)
208 return s;
210 s << " : ";
212 for (int i = 0; i < inits.size(); ++i)
214 String init (inits[i]);
216 while (init.endsWithChar (','))
217 init = init.dropLastCharacters (1);
219 s << init;
221 if (i < inits.size() - 1)
222 s << ",\n ";
223 else
224 s << "\n";
227 return s;
230 static const String getIncludeFileCode (StringArray files)
232 files.trim();
233 files.removeEmptyStrings();
234 files.removeDuplicates (false);
236 String s;
238 for (int i = 0; i < files.size(); ++i)
239 s << "#include \"" << files[i] << "\"\n";
241 return s;
244 //==============================================================================
245 static void replaceTemplate (String& text, const String& itemName, const String& value)
247 for (;;)
249 const int index = text.indexOf ("%%" + itemName + "%%");
251 if (index < 0)
252 break;
254 int indentLevel = 0;
256 for (int i = index; --i >= 0;)
258 if (text[i] == '\n')
259 break;
261 ++indentLevel;
264 text = text.replaceSection (index, itemName.length() + 4,
265 indentCode (value, indentLevel));
269 //==============================================================================
270 static bool getUserSection (const StringArray& lines, const String& tag, StringArray& resultLines)
272 const int start = indexOfLineStartingWith (lines, "//[" + tag + "]", 0);
274 if (start < 0)
275 return false;
277 const int end = indexOfLineStartingWith (lines, "//[/" + tag + "]", start + 1);
279 for (int i = start + 1; i < end; ++i)
280 resultLines.add (lines [i]);
282 return true;
285 static void copyAcrossUserSections (String& dest, const String& src)
287 StringArray srcLines, dstLines;
288 srcLines.addLines (src);
289 dstLines.addLines (dest);
291 for (int i = 0; i < dstLines.size(); ++i)
293 if (dstLines[i].trimStart().startsWith ("//["))
295 String tag (dstLines[i].trimStart().substring (3));
296 tag = tag.upToFirstOccurrenceOf ("]", false, false);
298 jassert (! tag.startsWithChar ('/'));
300 if (! tag.startsWithChar ('/'))
302 const int endLine = indexOfLineStartingWith (dstLines,
303 "//[/" + tag + "]",
304 i + 1);
306 if (endLine > i)
308 StringArray sourceLines;
310 if (getUserSection (srcLines, tag, sourceLines))
312 int j;
313 for (j = endLine - i; --j > 0;)
314 dstLines.remove (i + 1);
316 for (j = 0; j < sourceLines.size(); ++j)
317 dstLines.insert (++i, sourceLines [j].trimEnd());
319 ++i;
321 else
323 i = endLine;
329 dstLines.set (i, dstLines[i].trimEnd());
332 dest = dstLines.joinIntoString ("\n") + "\n";
335 //==============================================================================
336 void GeneratedCode::applyToCode (String& code,
337 const String& fileNameRoot,
338 const bool isForPreview,
339 const String& oldFileWithUserData) const
341 // header guard..
342 String headerGuard ("__JUCER_HEADER_");
343 headerGuard << className.toUpperCase().retainCharacters ("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
344 << "_" << fileNameRoot.toUpperCase().retainCharacters ("ABCDEFGHIJKLMNOPQRSTUVWXYZ")
345 << "_" << String::toHexString (Random::getSystemRandom().nextInt()).toUpperCase()
346 << "__";
347 replaceTemplate (code, "headerGuard", headerGuard);
349 replaceTemplate (code, "creationTime", Time::getCurrentTime().toString (true, true, true));
351 replaceTemplate (code, "className", className);
352 replaceTemplate (code, "constructorParams", constructorParams);
353 replaceTemplate (code, "initialisers", getInitialiserList());
355 replaceTemplate (code, "classDeclaration", getClassDeclaration());
356 replaceTemplate (code, "privateMemberDeclarations", privateMemberDeclarations);
357 replaceTemplate (code, "publicMemberDeclarations", getCallbackDeclarations() + "\n" + publicMemberDeclarations);
359 replaceTemplate (code, "methodDefinitions", getCallbackDefinitions());
361 replaceTemplate (code, "includeFilesH", getIncludeFileCode (includeFilesH));
362 replaceTemplate (code, "includeFilesCPP", getIncludeFileCode (includeFilesCPP));
364 replaceTemplate (code, "constructor", constructorCode);
365 replaceTemplate (code, "destructor", destructorCode);
367 if (! isForPreview)
369 replaceTemplate (code, "metadata", jucerMetadata);
370 replaceTemplate (code, "staticMemberDefinitions", staticMemberDefinitions);
372 else
374 replaceTemplate (code, "metadata", " << Metadata isn't shown in the code preview >>\n");
375 replaceTemplate (code, "staticMemberDefinitions", "// Static member declarations and resources would go here... (these aren't shown in the code preview)");
378 copyAcrossUserSections (code, oldFileWithUserData);